// This is the main DLL file.

#include "stdafx.h"

#include "XLoader.h"

using namespace msclr::interop;
using namespace System::Collections::Generic;

namespace XLoader
{
	XReader::XReader()
	{

	}


	GLModel^ XReader::ReadXModel(String^ sFilename)
	{
		m_pObj = new IO_Model_X();
		m_pModel = new Frm::Model3D();

		GLModel^ glModel = nullptr;

		if(LoadFromFile(sFilename) == true)
		{
			glModel = ProcessModel(m_pModel);
		}
		
		delete m_pModel;
		delete m_pObj;

		return glModel;
	}

	bool XReader::LoadFromFile(String^ sFilename)
	{
		std::string stdFilename = marshal_as<std::string>(sFilename);

		Frm::Model3D* mdl = new Frm::Model3D();
		bool result =  m_pObj->Load(stdFilename, mdl);
		m_pModel = mdl;

		return result;
	}

	GLColor^ ProcessColor(Frm::Color3 color)
	{
		GLColor^ glColor = gcnew GLColor();
		glColor->Red = color[0];
		glColor->Green = color[1];
		glColor->Blue = color[2];

		return glColor;
	}

	GLColor^ ProcessColor(Frm::Color4 color)
	{
		GLColor^ glColor = gcnew GLColor();
		glColor->Red = color[0];
		glColor->Green = color[1];
		glColor->Blue = color[2];

		return glColor;
	}


	GLMesh^ XReader::ProcessMesh(Frm::Mesh* mesh)
	{
		GLMesh^ glMesh = gcnew GLMesh();

		// convert vectors
		List<Vector3d>^ lstVertices = gcnew List<Vector3d>();
		//for(uint16 j = mesh->_FirstVertex; j < mesh->_FirstVertex + mesh->_nVertices; j++)
		for(uint16 j = 0; j < mesh->_nVertices; j++)
		{
			Vector3d vec;;
			vec.X = mesh->_Vertices[j][0];
			vec.Y = mesh->_Vertices[j][1];
			vec.Z = mesh->_Vertices[j][2];

			lstVertices->Add(vec);
		}
		glMesh->Vectors = lstVertices->ToArray();

		// convert normals
		lstVertices->Clear();
		//for(uint16 j = mesh->_FirstNormal; j < mesh->_FirstNormal + mesh->_nNormals; j++)
		for(uint16 j = 0; j < mesh->_nNormals; j++)
		{
			Vector3d vec;
			vec.X = mesh->_Normals[j].x;
			vec.Y = mesh->_Normals[j].y;
			vec.Z = mesh->_Normals[j].z;

			lstVertices->Add(vec);
		}
		glMesh->Normals = lstVertices->ToArray();

		// convert texture coordinates
		List<Vector2d>^ lstTextCoords = gcnew List<Vector2d>();
		//for(uint16 j = mesh->_FirstTextureCoord; j < mesh->_FirstTextureCoord + mesh->_nTextureCoords; j++)
		for(uint16 j = 0; j < mesh->_nTextureCoords; j++)
		{
			Vector2d vec;;
			vec.X = mesh->_TextureCoords[j][0];
			vec.Y = mesh->_TextureCoords[j][1];

			lstTextCoords->Add(vec);
		}
		glMesh->TexCoords = lstTextCoords->ToArray();

		// convert indices
		List<unsigned int>^ lstIndices = gcnew List<unsigned int>();
		//for(uint32 j = mesh->_FirstFace; j < mesh->_FirstFace + mesh->_nFaces; j++)
		for(uint32 j = 0; j < mesh->_nFaces; j++)
		{
			lstIndices->Add(mesh->_Faces[j][0]);
			lstIndices->Add(mesh->_Faces[j][1]);
			lstIndices->Add(mesh->_Faces[j][2]);
		}
		glMesh->Indices = lstIndices->ToArray();

		if(mesh->_nMaterials > 0)
		{
			GLMaterial^ glMat = gcnew GLMaterial();
			std::list<Frm::Material*>::iterator it = mesh->_Materials.begin();
			if(it != mesh->_Materials.end())
			{	
				glMat->DiffuseColor = ProcessColor((*it)->_FaceColor);
				glMat->SpecularColor = ProcessColor((*it)->_SpecularColor);
				glMat->EmissiveColor = ProcessColor((*it)->_EmissiveColor);
			}
		}

		return glMesh;
	}


	GLModel^ XReader::ProcessModel(Frm::Model3D* model)
	{
		GLModel^ glModel = gcnew GLModel();

		List<GLMesh^>^ lstMeshes = gcnew List<GLMesh^>();
		for(std::list<Frm::Mesh*>::iterator it = model->_Meshes.begin(); it != model->_Meshes.end(); it++)
		{
			lstMeshes->Add(ProcessMesh(*it));
		}
		glModel->Meshes = lstMeshes->ToArray();
		
		return glModel;
	}
}
